package com.liuwei.spring.cloud.biz.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.liuwei.spring.cloud.biz.repository.db.entity.LiFeignChain;
import com.liuwei.spring.cloud.biz.repository.db.mapper.LiFeignChainMapper;
import com.liuwei.spring.cloud.biz.service.LiLogService;
import com.liuwei.spring.cloud.common.utils.Jackson;
import com.liuwei.spring.cloud.common.utils.StringPool;
import com.liuwei.spring.cloud.framework.spring.ApplicationHelper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author : LiLogServiceImpl
 * @version V1.0
 * @date: 2024/5/6 5:33 PM
 * @Description: TODO
 */
@Slf4j
@Service
public class LiLogServiceImpl implements LiLogService {

    @Resource
    LiFeignChainMapper iLiFeignChainMapper;



    @Override
    public void syncHttpLog(String env, String cluster, String provider) {
        String query =
                """
                {env="prod", app="factory-dsc-logistics-searcher", pod_ip=~".*"} |= "feign-call"
                """;
        String source = """
                %7Benv%3D%22prod%22%2C%20app%3D%22factory-dsc-logistics-searcher%22%2C%20pod_ip%3D~%22.*%22%7D%20%7C%3D%20%22feign-call%22
                """;
        System.out.println(URLEncoder.encode(query, Charset.defaultCharset()));
        Long start = DateUtil.beginOfDay(DateUtil.date()).getTime();
        int minutes = 30;
        Long end = start - minutes*60 * 1000;
        int times = 30*24*60/minutes;
        //times = 1;
        for (int i =0;i<=times;i++){
            try {
                env = "prod";
                provider = "factory-dsc-logistics-searcher";
                String result = search(env,cluster,provider,"feign-call",String.valueOf(start*1000*1000),String.valueOf(end*1000*1000));
                dealHttpLogs(env,cluster,provider,result);
                Thread.sleep(1000);
            } catch (Exception e) {
                log.info(e.getMessage(),e);
            }
            // 重试时间间隔
            start = end;
            end = start - minutes*60 * 1000;
        }
    }

    private void dealHttpLogs(String env, String cluster, String provider, String result){
        List<String> lines = new ArrayList<>();
        JsonRootBean root = JSON.parseObject(result,JsonRootBean.class);
        CollectionUtils.emptyIfNull(root.getData().getResult()).forEach(x->{
            CollectionUtils.emptyIfNull(x.getValues()).forEach(m->{
                LogLine log = new LogLine();
                log.setValue(m[1]);
                String value = m[1];
                lines.add(value);
            });
        });
        dealLogLine(env,cluster,provider,lines);
    }

    @Override
    public void syncFileLog(String env, String cluster, String provider,String filePath) {
        File file = new File(filePath);
        if(!file.exists()){
            throw new RuntimeException(StrUtil.format("{} 文件不存在",filePath));
        }
        try {
            LineIterator it = FileUtils.lineIterator(file, StandardCharsets.UTF_8.toString());
            while (it.hasNext()) {
                String line = it.nextLine();
                // 处理读取到的每一行
                if(StringUtils.containsIgnoreCase(line,"feign-call")){
                    dealLogLine(env,cluster,provider, Arrays.asList(line));
                }
            }
            it.close(); // 关闭迭代器
        } catch (IORuntimeException | IOException e) {
            e.printStackTrace();
        }
    }


    private static void dealLogLine(String env,String cluster,String provider,List<String> loginfo){
        List<LogLine> logs = new ArrayList<>();
        CollectionUtils.emptyIfNull(loginfo).forEach(x->{
            LogLine log = new LogLine();
            log.setEnv(env);
            log.setCluster(cluster);
            log.setProvider(provider);

            String value = x;
            String time = StringUtils.substringAfter(value,"[v1] [");
            time = StringUtils.substringBefore(time,"]");
            log.setTime(time);

            String tid = StringUtils.substringAfter(value,"TID: ");
            tid = StringUtils.substringBefore(tid,"]");
            log.setTid(tid);

            String detail = StringUtils.substringAfterLast(value,"feign-call:");
            String[] splits = StringUtils.split(detail, StringPool.COMMA);
            String caller = splits[0];
            String clazz = splits[2];
            String method = splits[3];
            String uri = splits[4];
            log.setConsumer(caller);
            log.setClazz(clazz);
            log.setMethod(method);
            log.setUri(uri);
            logs.add(log);
        });
        log.info("LogLine:{}", Jackson.toJSONString(logs));
        ApplicationHelper.getBean(LiLogService.class).insertLogs(logs);
        /*List<String> lines = new ArrayList<>();
        CollectionUtils.emptyIfNull(logs).forEach(x->{
            String line = StringUtils.joinWith(StringPool.COMMA,x.getTime(),x.getConsumer(),x.getClazz(),x.getMethod(),x.getUri());
            lines.add(line);
        });
        File file = new File("/Users/liuwei19/Samsung/gitcode/workplace/dsc/caller.csv");
        FileUtil.appendLines(lines,file, StandardCharsets.UTF_8);
        */
    }

    @Async
    @Override
    public void insertLogs(List<LogLine> logs){
        if(CollectionUtils.isEmpty(logs)){
            return;
        }
        for (LogLine line:logs){
            LiFeignChain entity = new LiFeignChain();
            BeanUtils.copyProperties(line,entity);
            entity.setDeleted(false);
            LiFeignChain log = getFeignCall(entity.getTid(),entity.getConsumer(),entity.getUri());
            if(ObjectUtils.isEmpty(log)){
                iLiFeignChainMapper.insert(entity);
            }
        }
    }

    private LiFeignChain getFeignCall(String tid,String consumer,String uri){
        LambdaQueryWrapper<LiFeignChain> wrapper = new LambdaQueryWrapper();
        wrapper.eq(LiFeignChain::getTid,tid);
        wrapper.eq(LiFeignChain::getConsumer,consumer);
        wrapper.eq(LiFeignChain::getUri,uri);
        return iLiFeignChainMapper.selectOne(wrapper,false);
    }

    @lombok.Data
    public static class LogLine{
        private String env;
        private String cluster;
        private String provider;
        private String time;
        private String value;
        private String consumer;
        private String clazz;
        private String method;
        private String uri;
        private String tid;
    }

    private static String search(String env, String cluster,String app, String keywords, String start, String end) throws Exception {



        String url = """
                https://log.ops.lixiangoa.com/api/datasources/proxy/1/loki/api/v1/query_range?direction=BACKWARD&limit=500&query=%7Benv%3D%22prod%22%2C%20app%3D%22factory-dsc-logistics-searcher%22%2C%20pod_ip%3D~%22.*%22%7D%20%7C%3D%20%22feign-call%22&start=1711864311638000000&end=1714456311638000000&step=3600
                """;
        url = StringUtils.replaceFirst(url,"prod",env);
        url = StringUtils.replace(url,"factory-dsc-logistics-searcher",app);
        url = StringUtils.replace(url,"1711864311638000000",end);
        url = StringUtils.replace(url,"1714456311638000000",start);
        log.info("start:{} end:{} url:{}", DateUtil.date(time2Data(Long.parseLong(start)/1000000)),DateUtil.date(time2Data(Long.parseLong(end)/1000000)),url);

        String refer = """
                https://log.ops.lixiangoa.com/explore?orgId=1&left=%5B%22now-7d%22,%22now%22,%22cnbjfa01%22,%7B%22filters%22:%5B%7B%22text%22:%22feign-call%22,%22type%22:%7B%22label%22:%22%E5%8C%85%E5%90%AB%22,%22value%22:%22%7C%3D%22%7D,%22id%22:66886%7D%5D,%22env%22:%22prod%22,%22app%22:%22factory-dsc-logistics-searcher%22,%22expr%22:%22%7B%20env%3D%5C%22prod%5C%22,%20app%3D%5C%22factory-dsc-logistics-searcher%5C%22,pod_ip%3D~%5C%22.*%5C%22%7D%20%7C%3D%20%5C%22feign-call%5C%22%22,%22podIP%22:%22.*%22%7D%5D
                """;
        refer = StringUtils.replaceFirst(refer,"prod",env);
        refer = StringUtils.replaceFirst(refer,"cnbjfa01",cluster);
        refer = StringUtils.replace(refer,"factory-dsc-logistics-searcher",app);
        refer = StringUtils.replace(refer,"1711864311638000000",end);
        refer = StringUtils.replace(refer,"1714456311638000000",start);
        String result = get(url);
        log.info(result);
        JsonRootBean root = JSON.parseObject(result,JsonRootBean.class);
        return result;
    }

    private static Date time2Data(Long time){
        Timestamp timestamp = new Timestamp(time);
        Date date = new Date(timestamp.getTime());
        return date;
    }

    public static String get(String url) throws Exception {
        // 创建HTTP请求
        HttpRequest request = HttpRequest.get(url);

        // 发送请求
        HttpResponse response = request.execute();

        // 输出响应结果
        return response.body();

        /*URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        // 设置请求类型
        con.setRequestMethod("GET");
        int responseCode = con.getResponseCode();
        System.out.println("Response Code : " + responseCode);
        // 读取响应
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuilder response = new StringBuilder();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        // 打印结果
        return response.toString();*/
    }


    @lombok.Data
    public class JsonRootBean {
        private String status;
        private Data data;
    }

    @lombok.Data
    public class Data{
        List<Result> result;
    }

    @lombok.Data
    public class Result{
        List<String[]> values;
    }
}
